package com.example.socket.filter.session;

import com.example.socket.core.Message;
import com.example.socket.core.Session;
import com.example.socket.core.SessionContext;
import com.example.socket.filter.FilterHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.SocketAddress;
import java.util.concurrent.RejectedExecutionException;

/**
 * 会话管理过滤器，作为{@link SessionManager}的过滤器实现方式，用于管理的会话创建与关闭
 * @author frank
 */
@Sharable
public class SessionManagerFilter extends ChannelInboundHandlerAdapter implements FilterHandler {

    private static final Logger logger = LoggerFactory.getLogger(SessionManagerFilter.class);

    // IoFilterAdapter 对应方法的实现

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 找回SESSION
        Channel channel = ctx.channel();
        Message message = (Message) msg;
        sessionManager.attach(channel, message.getSession(), false);
        super.channelRead(ctx, msg);
    }


    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        try {
            Channel channel = ctx.channel();
            NettySession session = (NettySession) NettySessionManager.lookup(channel);
            if (session == null) {
                try {
                    if (channel.isOpen() || channel.isActive()) {
                        channel.close();
                    }
                } catch (Exception e) {
                    logger.error("强制连接[{}]异常", channel.remoteAddress(), e);
                }
                return;
            }
            SessionContext context = session.getContext();
            Object identity = null;
            if (context != null) {
                identity = context.getIdentity();
            }
            if (logger.isDebugEnabled()) {
                long sessionId = session.getId();
                SocketAddress remoteAddress = session.getRemoteAddress();
                logger.debug("连接[{}]会话[{}]关闭移除 - 用户[{}] 共发出[{}]条消息", remoteAddress, sessionId, identity, session.getCounter().get());
            }
            // 触发关闭
            sessionManager.onSessionClosed(session);
            // 分离SESSION
            sessionManager.detach(session, channel);
            super.channelInactive(ctx);
        } catch (RejectedExecutionException e) {
            logger.warn("java.util.concurrent.RejectedExecutionException: event executor terminated");
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        Session session = sessionManager.createSession(channel, creator);
        sessionManager.onSessionOpened(session, channel);
        logger.debug("连接[{}]会话[{}]创建添加", channel.remoteAddress(), session.getId());
        super.channelActive(ctx);
    }

    // ----

    /** SESSION管理器 */
    private NettySessionManager sessionManager;

    private NettySessionUtil creator = new NettySessionUtil();

    public SessionManagerFilter setSessionManager(SessionManager sessionManager) {
        this.sessionManager = (NettySessionManager) sessionManager;
        return this;
    }

    @Deprecated
    public void setHandlerName(String handlerName) {
        // 已废弃， 保留方法避免出错
    }

    @Override
    public int getOrder() {
        return 30;
    }

    @Override
    public String getName() {
        return "sessionManager";
    }
}
